package cn.toolck.my.spring.annotation;

import cn.toolck.my.spring.pojo.BeanDefinition;
import cn.toolck.my.spring.utils.FileUtils;
import cn.toolck.my.spring.utils.StringUtils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @ClassName AnnotationParse
 * @Description 进行注解解析
 * @Author Toolck Rin
 * @Date 2021/2/8 15:33
 * @Version 1.0
 **/
public class AnnotationParse {
    /**
     * 解析注解配置的bean
     * @param componentClass 解析带有Component或是Service的注解的类
     * @return 返回一个BeanDefinition
     * @throws InstantiationException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     * @throws NoSuchMethodException
     */
    public static BeanDefinition parseComponentAnno(Class<?> componentClass) throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
        // 获取Component的注解信息
        BeanDefinition beanDefinition = new BeanDefinition();
        Component annotation = componentClass.getAnnotation(Component.class);
        Service service = componentClass.getAnnotation(Service.class);
        beanDefinition.setClassName(componentClass);
        String id = annotation == null ? service.value() : annotation.value();
        if (StringUtils.isNullOrEmpty(id)) {
            id = componentClass.getSimpleName();
            id = StringUtils.getFirstLow(id);
        }
        beanDefinition.setName(id);
        Field[] fields = componentClass.getDeclaredFields();
        for (Field field : fields) {
            // 是否需要其他的bean进行注入
            if (field.isAnnotationPresent(Autowired.class)) {
                String name = field.getName();
                beanDefinition.getAutoFieldName().add(name);
            }
        }
        // 是否需要进行事务的代理
        Transactional transactional = hasTransactional(componentClass);
        if (transactional != null) {
            beanDefinition.setTransactional(transactional);
        }
        return beanDefinition;
    }

    /**
     * 判定收包含有Transactional注解扫描方法上的注解
     * @param componentClass 类
     * @return
     */
    private static Transactional hasTransactional(Class<?> componentClass) {
        Method[] methods = componentClass.getMethods();
        for (Method method : methods) {
            if (method.isAnnotationPresent(Transactional.class)) {
                Transactional transactional = method.getAnnotation(Transactional.class);
                return transactional;
            }
        }
        return null;
    }


}
